/////////////////////////////////////////////////////////////////////////////
// Name:        vifunc.h
// Purpose:     process keyevent like vim 
// Author:      Jia Wei
// Created:     2011/12/17
// Copyright:   (c) Jia Wei
// Licence:     wxWidgets licence
/////////////////////////////////////////////////////////////////////////////

#ifndef __VIFUNC_H__
#define __VIFUNC_H__

#ifdef __GNUG__
#pragma interface "vifunc.h"
#endif

#include <wx/hashmap.h>

class ViFunc;
typedef void (ViFunc::*vFunc)(wxScintilla*);

#define MAKE_PAIRS(mode,ekey,lastkeycode,keycode,value) do{ \
        unsigned long key = calcKey(mode,ekey,lastkeycode,keycode); \
        pairs[key] = value; \
    }while(0)

#define MAKE_CODE(code) (code-'a'+65)
#define GET_LINE(code) (code>>8 & 0xffff)
#define GET_KEYCODE(code) (code & 0xff)
#define BOOKMARK_MARKER        2

WX_DECLARE_HASH_MAP(unsigned long, vFunc, wxIntegerHash, wxIntegerEqual, LongHashMap);
WX_DECLARE_HASH_MAP( wxString, int, wxStringHash, wxStringEqual, StringHashMap);

enum eFKEY{ NONE, CTRL, SHIFT, ALT };
enum eMODE{ INSERT, NORMAL, VISUAL };

class ViFunc
{
    public:
        static ViFunc* instance()
        {
            return &gViFunc;
        }

        //keycode process entry
        bool execute(wxKeyEvent &event);

    private:
        //not allow construct
        ViFunc();
        ViFunc(const ViFunc&);
        ViFunc& operator=(const ViFunc&);

        //singleton instance
        static ViFunc gViFunc;

        //current edit mode
        eMODE gMode;
        //current keycode
        int keyCode;
        //store last keycode temporaly
        int keyCodes;
        //marker register now set only one (a) 
        StringHashMap markers;
        //store keycode maps
        LongHashMap pairs;

        unsigned long calcKey(
                eMODE mode, //vim normal/insert/visual mode
                eFKEY ekey, //if shift/ctrl/alt keycodes have pressed
                unsigned char lastkeycode, //record last keycode pressed, like gg(go document home)
                unsigned char keycode //current keycode
                )
        {
            return (mode << 4 | ekey) <<16 | lastkeycode << 8 | keycode;
        }

        wxString getActiveFile()
        {
            cbEditor *ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
            if (!ed)
            {
                return wxT("");
            }

            return ed->GetFilename();
        }


        //insert mode
        void i_esc(wxScintilla* editor);

        //normal mode
        void n_esc(wxScintilla* editor);
        void n_number(wxScintilla* editor);
        void n_h(wxScintilla* editor);
        void n_j(wxScintilla* editor);
        void n_k(wxScintilla* editor);
        void n_l(wxScintilla* editor);
        void n_i(wxScintilla* editor);
        void n_ctrl_f(wxScintilla* editor);
        void n_0(wxScintilla* editor);
        void n_sf_6(wxScintilla* editor);
        void n_sf_4(wxScintilla* editor);
        void n_dsf_4(wxScintilla* editor);
        void n_o(wxScintilla* editor);
        void n_O(wxScintilla* editor);
        void n_G(wxScintilla* editor);
        void n_g(wxScintilla* editor);
        void n_gg(wxScintilla* editor);
        void n_ctrl_b(wxScintilla* editor);
        void n_b(wxScintilla* editor);
        void n_e(wxScintilla* editor);
        void n_de(wxScintilla* editor);
        void n_d(wxScintilla* editor);
        void n_dd(wxScintilla* editor);
        void n_u(wxScintilla* editor);
        void n_y(wxScintilla* editor);
        void n_yy(wxScintilla* editor);
        void n_p(wxScintilla* editor);
        void n_sf_5(wxScintilla* editor);
        void n_x(wxScintilla* editor);
        void n_X(wxScintilla* editor);
        void n_v(wxScintilla* editor);
        void n_tab(wxScintilla* editor);
        void n_tabtab(wxScintilla* editor);
        void n_bktab(wxScintilla* editor);
        void n_bktabbktab(wxScintilla* editor);
        void n_ctrl_r(wxScintilla* editor);
        void n_search(wxScintilla* editor);
        void n_ctrl_n(wxScintilla* editor);
        void n_ctrl_p(wxScintilla* editor);
        void n_m(wxScintilla* editor);
        void n_a(wxScintilla* editor);
        void n_tom(wxScintilla* editor);
        void n_toma(wxScintilla* editor);

        //visual mode
        void v_esc(wxScintilla* editor);
        void v_h(wxScintilla* editor);
        void v_j(wxScintilla* editor);
        void v_k(wxScintilla* editor);
        void v_l(wxScintilla* editor);
        void v_e(wxScintilla* editor);
        void v_b(wxScintilla* editor);
        void v_sf_6(wxScintilla* editor);
        void v_0(wxScintilla* editor);
        void v_sf_4(wxScintilla* editor);
        void v_tab(wxScintilla* editor);
        void v_bktab(wxScintilla* editor);
        void v_y(wxScintilla* editor);
        void v_d(wxScintilla* editor);
        
};



#endif  //__VIFUNC_H__
